'''
Created on Oct 22, 2009

@author: CommisGordon
'''
import pygame,math,network,gamegraphics,time,gameroot



#Container for the user controlled player
class Player(gamegraphics.GameDrawable):
    def __init__(self,root,imgloc,xpos = 0, ypos = 0,username=None):
        gamegraphics.GameDrawable.__init__(self,root,imgloc)
        self.accel=.5
        self.xpos = xpos
        self.ypos = ypos
        self.scale = 1
        self.vx = 0
        self.vy = 0
        self.root = root
        self.shieldDrawable = gamegraphics.GameDrawable(root, str(gameroot.respath+"shield.png"))
        self.midx = self.root.prefs["resolution"][0]/2
        self.midy = self.root.prefs["resolution"][1]/2
        self.drawx = self.midx-(self.image.get_width()/2)
        self.drawy = self.midy-(self.image.get_height()/2)
        self.health = 100
        self.mhealth = 100
        self.mshield =100
        self.shield = 100
        self.energy = 100
        self.rotation = 0
        self.lastrot = 0
        self.surface = pygame.display.get_surface()
        self.raccel = .4
        self.maxv = 175
        self.conts = []
        self.nconts = []
        self.newDeaths = []
        self.pid =0
        self.username = username
        
    #Update method, handles 
    def update(self,time):
        
        #Handle backwards/forwards
        if (network.MOVE_FORWARD in self.conts) ^ (network.MOVE_BACKWARD in self.conts):
            if network.MOVE_FORWARD in self.conts:
                self.vx += math.cos(math.pi*self.rotation/180)*self.accel*(time)/5
                self.vy -= math.sin(math.pi*self.rotation/180)*self.accel*(time)/5
            elif network.MOVE_BACKWARD in self.conts:
                self.vx -= math.cos(math.pi*self.rotation/180)*self.accel*(time)/5
                self.vy += math.sin(math.pi*self.rotation/180)*self.accel*(time)/5


        #Handle left/right
        if (network.ROTATE_LEFT in self.conts) and (network.ROTATE_RIGHT in self.conts):
            pass
        elif network.ROTATE_LEFT in self.conts:
            self.rotation += (self.raccel*time)
        elif network.ROTATE_RIGHT in self.conts:
            self.rotation -= (self.raccel*time)
            
        #Keep rotation within reasonable values
        if(self.rotation>360):
            self.rotation = self.rotation-360
        elif(self.rotation<0):
            self.rotation = self.rotation+360
        
        #Max out velocity
        if self.vx > self.maxv:
            self.vx = self.maxv
        if self.vy > self.maxv:
            self.vy=self.maxv
        if self.vx < -self.maxv:
            self.vx = -self.maxv
        if self.vy < -self.maxv:
            self.vy = -self.maxv
        
        #Decelerate
        self.vy = self.vy*(1-self.accel*time/2000)
        self.vx = self.vx*(1-self.accel*time/2000)
        
        #Set position based on velocity and time
        self.xpos += self.vx*time/100
        self.ypos += self.vy*time/100
        
        self.shieldDrawable.xpos = self.xpos
        self.shieldDrawable.ypos = self.ypos
        self.shieldDrawable.scale = self.scale
        
        if self.shield>=self.mshield:
            self.shield = self.mshield
        else:
            self.shield += .001*time      
        if self.health==0:
            self.xpos = 0
            self.ypos= 0
            self.vx = 0
            self.vy=0
            self.health=self.mhealth
            self.shield=self.mshield
        
        
    #Update method, handles 
    def handleControls(self):
        if network.MOVE_FORWARD not in self.conts and self.root.monitor.getstate(self.root.prefs["key_thrust"]):
            self.conts.append(network.MOVE_FORWARD)
            if(network.S_MOVE_FORWARD in self.conts):
                self.conts.remove(network.S_MOVE_FORWARD)
            self.nconts.append(network.MOVE_FORWARD)
        if network.MOVE_BACKWARD not in self.conts and self.root.monitor.getstate(self.root.prefs["key_stabilize"]):
            self.conts.append(network.MOVE_BACKWARD)
            if(network.S_MOVE_BACKWARD in self.conts):
                self.conts.remove(network.S_MOVE_BACKWARD)
            self.nconts.append(network.MOVE_BACKWARD)
        if network.ROTATE_LEFT not in self.conts and self.root.monitor.getstate(self.root.prefs["key_rotateleft"]):
            self.conts.append(network.ROTATE_LEFT)
            if network.S_ROTATE_LEFT in self.conts:
                self.conts.remove(network.S_ROTATE_LEFT)
            self.nconts.append(network.ROTATE_LEFT)
        if network.ROTATE_RIGHT not in self.conts and self.root.monitor.getstate(self.root.prefs["key_rotateright"]):
            self.conts.append(network.ROTATE_RIGHT)
            if network.S_ROTATE_RIGHT in self.conts:
                self.conts.remove(network.S_ROTATE_RIGHT)
            self.nconts.append(network.ROTATE_RIGHT)
        if network.MOVE_FORWARD in self.conts and not self.root.monitor.getstate(self.root.prefs["key_thrust"]):
            self.conts.remove(network.MOVE_FORWARD)
            self.conts.append(network.S_MOVE_FORWARD)
            self.nconts.append(network.S_MOVE_FORWARD)
        if network.MOVE_BACKWARD in self.conts and not self.root.monitor.getstate(self.root.prefs["key_stabilize"]):
            self.conts.remove(network.MOVE_BACKWARD)
            self.conts.append(network.S_MOVE_BACKWARD)
            self.nconts.append(network.S_MOVE_BACKWARD)
        if network.ROTATE_LEFT in self.conts and not self.root.monitor.getstate(self.root.prefs["key_rotateleft"]):
            self.conts.remove(network.ROTATE_LEFT)
            self.conts.append(network.S_ROTATE_LEFT)
            self.nconts.append(network.S_ROTATE_LEFT)
        if network.ROTATE_RIGHT in self.conts and not self.root.monitor.getstate(self.root.prefs["key_rotateright"]):
            self.conts.remove(network.ROTATE_RIGHT)
            self.conts.append(network.S_ROTATE_RIGHT)
            self.nconts.append(network.S_ROTATE_RIGHT)
        if self.root.monitor.getjustpressed(self.root.prefs["key_shoot"]):
            self.conts.append(network.SHOOT_BULLET)
            self.nconts.append(network.SHOOT_BULLET)


    
    #Paint the player to the screen
    def repaint(self):
        self.image = pygame.transform.rotate(self.orig,self.rotation)
        self.drawx = self.midx - (self.image.get_width()/2)
        self.drawy = self.midy - (self.image.get_height()/2)
        self.surface.blit(self.image,(self.drawx,self.drawy))
        
    def getControls(self):
        temp = self.nconts
        self.nconts = []
        return temp
    
    #############################################
    def draw(self,camera):
        gamegraphics.GameDrawable.draw(self, camera)
        self.shieldDrawable.draw(camera)
        

############################################################
# Enemy class
# This class holds all of the data about a generic enemy
# is handled by the AIFactory module. Every player
# entity which is not the currently controlled player
# will be one of these
#############################################################            
class Enemy(gamegraphics.GameDrawable):
    def __init__(self,root,image,ai,pid=None,pos = (0,0),rotation=0,velocity = (0,0),acceleration=(.5,.4),health=(100,100),shield=(100,100),energy=(100,100),username=None):
        gamegraphics.GameDrawable.__init__(self,root,image)
        self.xpos = pos[0]
        self.ypos = pos[1]
        self.rotation = rotation
        self.shieldDrawable = gamegraphics.GameDrawable(root, str(gameroot.respath+"shield.png"))
        self.vx = velocity[0]
        self.vy = velocity[1]
        self.accel = acceleration[0]
        self.raccel = acceleration[1]
        self.health = health[0]
        self.mhealth = health[1]
        self.shield = shield[0]
        self.mshield = shield[1]
        self.energy = energy[0]
        self.menergy = energy[1]
        self.maxv = 175
        self.conts = []
        self.ai = ai
        self.pid = pid
        self.username = username


    def update(self,t):
        #New controls from the ai module
        controls = self.ai.getCommands()
        
        #Controls to remove from the current controls tate
        removal = []
        
        #If im already doing it, dont do it again
        for c in controls:
            if c in self.conts:
                removal.append(c)
        for c in removal:
            controls.remove(c)
            
        #If the control is a set of data holding positional information, process it as such
        for c in controls:
            if type(c).__name__ == 'tuple':
                #Move us to where the player actually is
                self.xpos = float(c[0])
                self.ypos = float(c[1])
                self.rotation = float(c[2])
                self.vx = float(c[3])
                self.vy = float(c[4])
                #Replace time with time since their update for interpolation
                lastupdate = float(c[5])
                self.health = c[6];
                self.shield = c[7];
                self.username = c[8];
                t=lastupdate
        
        #Sort out controls to ensure we're not doing two opposites at the same time            
        if network.MOVE_FORWARD in controls:
            self.conts.append(network.MOVE_FORWARD)
        if network.S_MOVE_FORWARD in controls and network.MOVE_FORWARD in self.conts:
            self.conts.remove(network.MOVE_FORWARD)
        if network.MOVE_BACKWARD in controls:
            self.conts.append(network.MOVE_BACKWARD)
        if network.S_MOVE_BACKWARD in controls and network.MOVE_BACKWARD in self.conts:
            self.conts.remove(network.MOVE_BACKWARD)
        if network.ROTATE_LEFT in controls:
            self.conts.append(network.ROTATE_LEFT)
        if network.S_ROTATE_LEFT in controls and network.ROTATE_LEFT in self.conts:
            self.conts.remove(network.ROTATE_LEFT)
        if network.ROTATE_RIGHT in controls:
            self.conts.append(network.ROTATE_RIGHT)
        if network.S_ROTATE_RIGHT in controls and network.ROTATE_RIGHT in self.conts:
            self.conts.remove(network.ROTATE_RIGHT)
        
        #Move forward/backward based on acceleration and time
        if network.MOVE_FORWARD in self.conts:
            self.vx += math.cos(math.pi*self.rotation/180)*self.accel*(t)/5
            self.vy -= math.sin(math.pi*self.rotation/180)*self.accel*(t)/5
        if network.MOVE_BACKWARD in self.conts:
            self.vx -= math.cos(math.pi*self.rotation/180)*self.accel*(t)/5
            self.vy += math.sin(math.pi*self.rotation/180)*self.accel*(t)/5
        
        #Rotate left and raight based on rotational acceleration and time
        if network.ROTATE_LEFT in self.conts:
            self.rotation += (self.raccel*t)
        if network.ROTATE_RIGHT in self.conts:
            self.rotation -= (self.raccel*t)
                
        #Keep rotation within reasonable values
        if(self.rotation>360):
            self.rotation = self.rotation-360
        elif(self.rotation<0):
            self.rotation = self.rotation+360
            
        #Max out velocity
        if self.vx > self.maxv:
            self.vx = self.maxv
        if self.vy > self.maxv:
            self.vy=self.maxv
        if self.vx < -self.maxv:
            self.vx = -self.maxv
        if self.vy < -self.maxv:
            self.vy = -self.maxv
        
        #Decelerate
        self.vy = self.vy*(1-self.accel*t/2000)
        self.vx = self.vx*(1-self.accel*t/2000)
        
        #Set position based on velocity and time
        self.xpos += self.vx*t/100
        self.ypos += self.vy*t/100          
        
        self.shieldDrawable.xpos = self.xpos
        self.shieldDrawable.ypos = self.ypos
        self.shieldDrawable.scale = self.scale
        
        if self.shield>=self.mshield:
            self.shield = self.mshield
        else:
            self.shield += .001*t       
        
        #We died, go back to center      
        if self.health==0:
            self.xpos = 0
            self.ypos= 0
            self.vx = 0
            self.vy=0
            self.health=self.mhealth
            self.shield=self.mshield
            
    #draw the enemy
    def repaint(self,x,y):
        self.image = pygame.transform.rotate(self.orig,self.rotation)
        self.drawx = self.xpos - x - self.image.get_width()/2
        self.drawy = self.ypos - y - self.image.get_height()/2
        self.surface.blit(self.image,(self.drawx,self.drawy))
        
        
        
    #############################################
    def draw(self,camera):
        gamegraphics.GameDrawable.draw(self, camera)
        self.shieldDrawable.draw(camera)    
        
        
############################################################
# Bullet class
# This class holds all of the data about a generic enemy
# is handled by the AIFactory module. Every player
# entity which is not the currently controlled player
# will be one of these
#############################################################            
class Bullet(gamegraphics.GameDrawable):
    def __init__(self,root,image,bid=None,pid=None,startpos = (0,0),rotation=0,timeshot=time.time(),velocity = (1,1)):
        gamegraphics.GameDrawable.__init__(self,root,image)
        self.xpos = startpos[0]
        self.ypos = startpos[1]
        self.startxpos = startpos[0]
        self.startypos = startpos[1]
        self.rotation = rotation
        self.vx = velocity[0]
        self.vy = velocity[1]
        self.maxv = 175
        self.bid = bid
        self.pid = pid
        self.timeshot = timeshot
        self.scale = 1
        self.recycle = False

    def update(self,t):
        #Set position based on velocity and time
        self.vx = math.cos(math.pi*self.rotation/180)
        self.vy = -math.sin(math.pi*self.rotation/180)
        t = (time.time()-self.timeshot)
        self.xpos = self.xpos+self.vx*(t)*1000
        self.ypos = self.ypos+self.vy*(t)*1000      
        
        
              
    